package dao

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"smart-health-platforms/config"
	"smart-health-platforms/pkg"
	"strconv"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.uber.org/zap"
)

// 心跳健康报告结构体
type HeartbeatReport struct {
	UserID          uint64                    `json:"user_id"`          // 用户ID
	RecordCount     int                       `json:"record_count"`     // 记录总数
	TimeRange       TimeRange                 `json:"time_range"`       // 测量时间范围
	Heartbeat       HeartbeatStats            `json:"heartbeat"`        // 心跳统计
	HealthAdvice    []string                  `json:"health_advice"`    // 健康建议
	DetailedRecords []HeartbeatDetailedRecord `json:"detailed_records"` // 详细记录
	CreatedAt       string                    `json:"created_at"`       // 报告生成时间
}

// 心跳详细记录
type HeartbeatDetailedRecord struct {
	RecordID       string  `json:"record_id"`       // 记录ID（ObjectID字符串）
	DeviceID       uint64  `json:"device_id"`       // 设备ID
	CollectionTime string  `json:"collection_time"` // 采集时间（可读格式）
	Heartbeat      float32 `json:"heartbeat"`       // 心跳值（次/分钟）
	Status         string  `json:"status"`          // 状态（正常/偏高/偏低）
}

// 心跳统计数据
type HeartbeatStats struct {
	Max   float32 `json:"max"`   // 最大心跳
	Min   float32 `json:"min"`   // 最小心跳
	Avg   float32 `json:"avg"`   // 平均心跳
	Unit  string  `json:"unit"`  // 单位（次/分钟）
	Trend string  `json:"trend"` // 趋势（上升/下降/平稳）
}

// 查询用户的心跳记录（带时间排序）
func queryHeartbeatRecords(userID uint64, collectionName string) ([]bson.M, error) {
	collection := config.HealthDB.Collection(collectionName)
	filter := bson.M{"user_id": userID}
	// 按采集时间升序排序，确保数据时序正确
	sort := bson.M{"collection_time": 1}

	cursor, err := collection.Find(
		context.Background(),
		filter,
		options.Find().SetSort(sort),
	)
	if err != nil {
		pkg.Warn("查询心跳数据失败", zap.Error(err))
		return nil, fmt.Errorf("查询失败: %w", err)
	}
	defer cursor.Close(context.Background())

	var records []bson.M
	if err := cursor.All(context.Background(), &records); err != nil {
		pkg.Warn("解析心跳记录失败", zap.Error(err))
		return nil, fmt.Errorf("解析失败: %w", err)
	}
	return records, nil
}

// 生成健康建议
func generateHeartbeatHealthAdvice(stats HeartbeatStats) []string {
	var advice []string

	// 基础健康知识
	advice = append(advice, "正常成年人静息心跳范围：60-100次/分钟，运动员可能偏低（50-60次/分钟）。")

	// 基于平均值的建议
	switch {
	case stats.Avg > 120:
		advice = append(advice, "您的平均心跳显著偏高（>120次/分钟），建议立即就医检查。")
	case stats.Avg > 100:
		advice = append(advice, "您的平均心跳偏高（>100次/分钟），可能存在心动过速，建议减少剧烈运动并休息。")
	case stats.Avg < 50:
		advice = append(advice, "您的平均心跳显著偏低（<50次/分钟），建议咨询医生评估心脏功能。")
	case stats.Avg < 60:
		advice = append(advice, "您的平均心跳偏低（<60次/分钟），若为运动员属正常，否则请关注是否有头晕等症状。")
	default:
		advice = append(advice, "您的平均心跳在正常范围内，继续保持良好生活习惯。")
	}

	// 基于趋势的建议
	switch stats.Trend {
	case "上升":
		advice = append(advice, "心跳呈上升趋势，请注意是否存在过度疲劳或压力过大。")
	case "下降":
		advice = append(advice, "心跳呈下降趋势，若伴随规律锻炼属正常，否则建议关注身体变化。")
	case "平稳":
		advice = append(advice, "心跳保持稳定，状态良好。")
	default:
		advice = append(advice, "数据不足，无法判断心跳趋势。")
	}

	// 通用建议
	advice = append(advice, "建议：保持规律作息，每天适度运动30分钟，避免熬夜和过度劳累。")
	return advice
}

// 分析心跳趋势
func analyzeHeartbeatTrend(records []HeartbeatDetailedRecord) string {
	if len(records) < 3 {
		return "数据不足，无法判断趋势"
	}

	// 取前半段和后半段数据的平均值对比
	mid := len(records) / 2
	earlyCount := min(3, mid)
	lateCount := min(3, len(records)-mid)

	var earlyAvg, lateAvg float32
	for i := 0; i < earlyCount; i++ {
		earlyAvg += records[i].Heartbeat
	}
	earlyAvg /= float32(earlyCount)

	for i := len(records) - lateCount; i < len(records); i++ {
		lateAvg += records[i].Heartbeat
	}
	lateAvg /= float32(lateCount)

	// 趋势判断阈值：5次/分钟
	const threshold = 5
	if lateAvg-earlyAvg > threshold {
		return "上升"
	} else if earlyAvg-lateAvg > threshold {
		return "下降"
	}
	return "平稳"
}

// 辅助函数：取最小值
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// 解析时间字段
func parseTimeField(timeField interface{}) (time.Time, error) {
	switch v := timeField.(type) {
	case time.Time:
		return v, nil
	case string:
		// 尝试解析为时间戳
		if ts, err := strconv.ParseInt(v, 10, 64); err == nil {
			return time.Unix(ts, 0), nil
		}
		// 尝试解析为时间字符串
		if t, err := time.Parse("2006-01-02 15:04:05", v); err == nil {
			return t, nil
		}
		return time.Time{}, fmt.Errorf("无法解析时间字符串: %s", v)
	case int64:
		return time.Unix(v, 0), nil
	case float64:
		return time.Unix(int64(v), 0), nil
	default:
		return time.Time{}, fmt.Errorf("不支持的时间类型: %T", v)
	}
}

// 解析设备ID字段
func parseDeviceID(deviceID interface{}) (uint64, error) {
	switch v := deviceID.(type) {
	case int64:
		return uint64(v), nil
	case int32:
		return uint64(v), nil
	case int:
		return uint64(v), nil
	case float64:
		return uint64(v), nil
	case string:
		if id, err := strconv.ParseUint(v, 10, 64); err == nil {
			return id, nil
		}
		return 0, fmt.Errorf("无法解析设备ID字符串: %s", v)
	default:
		return 0, fmt.Errorf("不支持的设备ID类型: %T", v)
	}
}

// 生成心跳健康报告
func GenerateHeartbeatReport(userID uint64, collectionName string) (*HeartbeatReport, error) {
	// 1. 查询数据
	records, err := queryHeartbeatRecords(userID, collectionName)
	if err != nil {
		return nil, fmt.Errorf("获取记录失败: %w", err)
	}

	// 2. 处理记录
	detailedRecords := make([]HeartbeatDetailedRecord, 0, len(records))
	var totalHeartbeat float32
	var maxHeartbeat, minHeartbeat float32
	var earliestTime, latestTime time.Time

	for i, record := range records {
		// 解析时间
		ts, err := parseTimeField(record["collection_time"])
		if err != nil {
			log.Printf("跳过无效时间记录 (id=%v): %v", record["_id"], err)
			continue
		}

		// 解析心跳值
		hbVal, ok := record["result"].(float64)
		if !ok {
			// 尝试其他数值类型
			if hbInt, ok := record["result"].(int32); ok {
				hbVal = float64(hbInt)
			} else if hbInt, ok := record["result"].(int64); ok {
				hbVal = float64(hbInt)
			} else {
				log.Printf("跳过无效心跳值记录: %v", record["_id"])
				continue
			}
		}
		heartbeat := float32(hbVal)

		// 统计计算
		totalHeartbeat += heartbeat
		if i == 0 {
			maxHeartbeat, minHeartbeat = heartbeat, heartbeat
			earliestTime, latestTime = ts, ts
		} else {
			if heartbeat > maxHeartbeat {
				maxHeartbeat = heartbeat
			}
			if heartbeat < minHeartbeat {
				minHeartbeat = heartbeat
			}
			if ts.Before(earliestTime) {
				earliestTime = ts
			}
			if ts.After(latestTime) {
				latestTime = ts
			}
		}

		// 状态判断
		var status string
		switch {
		case heartbeat > 100:
			status = "偏高"
		case heartbeat < 60:
			status = "偏低"
		default:
			status = "正常"
		}

		// 解析设备ID
		deviceID, err := parseDeviceID(record["device_id"])
		if err != nil {
			log.Printf("跳过无效设备ID记录 (id=%v): %v", record["_id"], err)
			continue
		}

		// 处理记录ID（ObjectID转换为字符串）
		var recordID string
		if objID, ok := record["_id"].(primitive.ObjectID); ok {
			recordID = objID.Hex()
		} else if idStr, ok := record["_id"].(string); ok {
			recordID = idStr
		} else if idInt, ok := record["_id"].(int64); ok {
			recordID = strconv.FormatInt(idInt, 10)
		} else {
			recordID = fmt.Sprintf("%v", record["_id"])
		}

		// 添加详细记录
		detailedRecords = append(detailedRecords, HeartbeatDetailedRecord{
			RecordID:       recordID,
			DeviceID:       deviceID,
			CollectionTime: ts.Format("2006-01-02 15:04:05"),
			Heartbeat:      heartbeat,
			Status:         status,
		})
	}

	// 3. 处理空记录场景
	recordCount := len(detailedRecords)
	log.Println(detailedRecords)
	if recordCount == 0 {
		return &HeartbeatReport{
			UserID:      userID,
			RecordCount: 0,
			TimeRange: TimeRange{
				Earliest: "无记录",
				Latest:   "无记录",
			},
			Heartbeat: HeartbeatStats{
				Max:   0,
				Min:   0,
				Avg:   0,
				Unit:  "次/分钟",
				Trend: "无数据",
			},
			HealthAdvice:    []string{"暂无心跳记录，无法生成健康建议。请先进行心跳测量。"},
			DetailedRecords: detailedRecords,
			CreatedAt:       time.Now().Format("2006-01-02 15:04:05"),
		}, nil
	}

	// 4. 生成统计数据
	avgHeartbeat := totalHeartbeat / float32(recordCount)
	trend := analyzeHeartbeatTrend(detailedRecords)

	// 5. 构建报告
	return &HeartbeatReport{
		UserID:      userID,
		RecordCount: recordCount,
		TimeRange: TimeRange{
			Earliest: earliestTime.Format("2006-01-02 15:04:05"),
			Latest:   latestTime.Format("2006-01-02 15:04:05"),
		},
		Heartbeat: HeartbeatStats{
			Max:   maxHeartbeat,
			Min:   minHeartbeat,
			Avg:   avgHeartbeat,
			Unit:  "次/分钟",
			Trend: trend,
		},
		HealthAdvice: generateHeartbeatHealthAdvice(HeartbeatStats{
			Max:   maxHeartbeat,
			Min:   minHeartbeat,
			Avg:   avgHeartbeat,
			Unit:  "次/分钟",
			Trend: trend,
		}),
		DetailedRecords: detailedRecords,
		CreatedAt:       time.Now().Format("2006-01-02 15:04:05"),
	}, nil
}

// 保存报告到文件
func SaveHeartbeatReportToFile(report *HeartbeatReport, dir string) (string, error) {
	if err := os.MkdirAll(dir, 0755); err != nil {
		return "", fmt.Errorf("创建目录失败: %w", err)
	}

	filename := fmt.Sprintf("heartbeat_report_%d_%d.json",
		report.UserID, time.Now().Unix())
	filePath := filepath.Join(dir, filename)

	data, err := json.MarshalIndent(report, "", "  ")
	if err != nil {
		return "", fmt.Errorf("序列化失败: %w", err)
	}

	if err := os.WriteFile(filePath, data, 0644); err != nil {
		return "", fmt.Errorf("写入文件失败: %w", err)
	}
	return filePath, nil
}

// 生成并保存报告
func GenerateAndSaveHeartbeatReports(userID uint64, dir string, collectionName string) (*HeartbeatReport, string, error) {
	report, err := GenerateHeartbeatReport(userID, collectionName)
	if err != nil {
		return nil, "", fmt.Errorf("生成报告失败: %w", err)
	}

	path, err := SaveHeartbeatReportToFile(report, dir)
	if err != nil {
		return report, "", fmt.Errorf("保存报告失败: %w", err)
	}
	return report, path, nil
}
